package com.guosen.zebra.framework.starter.idm.ldap.service.impl;

import com.guosen.zebra.framework.starter.idm.ldap.constants.IdmLdapAttributes;
import com.guosen.zebra.framework.starter.idm.ldap.properties.IdmLdapProperties;
import com.guosen.zebra.framework.starter.idm.ldap.service.IdmLdapExecuteService;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapContext;
import java.util.*;

/**
 * 实际查询实现
 */
public class IdmLdapExecuteServiceImpl implements IdmLdapExecuteService {

    private static final String SIMPLE = "simple";

    public static final String LDAP_CTX_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";

    private IdmLdapProperties idmLdapProperties;

    public IdmLdapExecuteServiceImpl(IdmLdapProperties idmLdapProperties) {
        this.idmLdapProperties = idmLdapProperties;
    }

    @Override
    public List<Map<String, String>> consumeServiceWithCustomConfiguration(String searchBase, String searchFilter,
                                             String[] returnedAttrs) throws Exception {
        List<Map<String, String>> result = new ArrayList<>();
        Hashtable<String, String> environment = buildEnvironment();
        LdapContext ctx = new InitialLdapContext(environment, null);
        // Create the
        SearchControls searchCtrl = new SearchControls();
        // 搜索子节点和孙子节点 // Specify
        searchCtrl.setSearchScope(SearchControls.SUBTREE_SCOPE);
        // 设置返回属性集
        searchCtrl.setReturningAttributes(returnedAttrs);
        NamingEnumeration<SearchResult> answer = ctx.search(searchBase, searchFilter, searchCtrl);
        while (answer.hasMoreElements()) {
            updateResult(result, answer.next());
        }
        ctx.close();
        return result;
    }

    private Hashtable<String, String> buildEnvironment() {
        Hashtable<String, String> hashEnv = new Hashtable<>();
        // LDAP访问安全级别
        hashEnv.put(Context.SECURITY_AUTHENTICATION, SIMPLE);
        // AD User
        hashEnv.put(Context.SECURITY_PRINCIPAL, idmLdapProperties.getUser());
        // AD Password
        hashEnv.put(Context.SECURITY_CREDENTIALS, idmLdapProperties.getPwd());
        // LDAP工厂类
        hashEnv.put(Context.INITIAL_CONTEXT_FACTORY, LDAP_CTX_FACTORY);
        // LDAP连接Url
        hashEnv.put(Context.PROVIDER_URL, idmLdapProperties.getUrl());
        return hashEnv;
    }

    private void updateResult(List<Map<String, String>> result, SearchResult sr) throws NamingException {
        String key = null;
        String value = null;
        Map<String,String> map = new HashMap<>();
        Attributes attrs = sr.getAttributes();
        if (attrs != null) {
            for (NamingEnumeration<? extends Attribute> ne = attrs.getAll(); ne.hasMore();) {
                Attribute attr = ne.next();
                key = attr.getID();
                // 读取属性值
                if (IdmLdapAttributes.SMART_CIPHER_TEXT.equals(key) || IdmLdapAttributes.SMART_SIGN.equals(key)){
                    continue;
                }
                for (NamingEnumeration<?> e = attr.getAll(); e.hasMore();) {
                    value = e.next().toString();
                }
                map.put(key, value);
            }
            result.add(map);
            // 更新数据
        }
    }
}
